﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "WallObjectCustomizedSerialization.h"
#include <sstream>
#include <iterator>
#include "Wall.h"
#include "UiDocumentViewUtils.h"
#include "IDocument.h"
#include "IUiDocument.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;
using namespace Sample;

WallObjectCloneBehavior * WallObjectCloneBehavior::Get(const IDbObject * pObject)
{
    static WallObjectCloneBehavior s_instance;
    s_instance.SetDbObject(pObject);
    return &s_instance;
}

OwnerPtr<IDbObject> WallObjectCloneBehavior::CloneObject()
{
    if (const WallObject * pWallObject = dynamic_cast<const WallObject*>(m_pObject))
    {
        return pWallObject->DeepCopy();
    }
    return nullptr;
}

void WallObjectCloneBehavior::SetDbObject(const IDbObject * pObject)
{
    m_pObject = pObject;
}

ISerializationBehavior * WallObjectSerializationBehavior::Get(const IDbObject * pObject)
{
    static WallObjectSerializationBehavior s_default;
    s_default.SetDbObject(pObject);
    return &s_default;
}

void WallObjectSerializationBehavior::SetDbObject(const IDbObject * pIObject)
{
    m_pObject = pIObject;
}

void WallObjectSerializationBehavior::Serialize(std::vector<char> & bytes)
{
    const WallObject* pWallObject = dynamic_cast<const WallObject*>(m_pObject);
    if (pWallObject)
    {
        const WallData* pData = pWallObject->GetData();
        Vector3d startPt = pData->GetStartPoint();
        Vector3d endPt = pData->GetEndPoint();
        std::stringstream stream;
        stream << StringUtil::ToString(pWallObject->GetName()) << std::endl;
        stream << pData->GetWidth() << std::endl;
        stream << pData->GetHeight() << std::endl;
        stream << startPt.X() << std::endl << startPt.Y() << std::endl << startPt.Z() << std::endl;
        stream << endPt.X() << std::endl << endPt.Y() << std::endl << endPt.Z() << std::endl;
        std::string buffer = stream.str();
        bytes.assign(buffer.begin(), buffer.end());
    }
}

double ToDouble(const std::string& str)
{
    bool bOK = true;
    double dVal = StringUtil::ToNumber<double>(str, &bOK);
    if (!bOK)
    {
        dVal = 0.;
    }
    return dVal;
}


bool WallObjectUnserializationBehavior::ConstructObject(const std::vector<char> & bytes, gcmp::OwnerPtr<IDbObject> & opIDbObject)
{
    std::stringstream stream;
    std::copy(bytes.begin(), bytes.end(),std::ostream_iterator<char>(stream));

    OwnerPtr<WallData> opData = NEW_AS_OWNER_PTR(WallData);

    std::string name;
    std::getline(stream, name);
    
    {
        std::string str;
        std::getline(stream, str);
        double dVal = ToDouble(str);
        opData->SetWidth(dVal);
    }
    {
        std::string str;
        std::getline(stream, str);
        double dVal = ToDouble(str);
        opData->SetHeight(dVal);
    }
    {
        std::string strX, strY, strZ;
        std::getline(stream, strX);
        std::getline(stream, strY);
        std::getline(stream, strZ);
        opData->SetStart(Vector3d{ToDouble(strX), ToDouble(strY), ToDouble(strZ)});
    }
    {
        std::string strX, strY, strZ;
        std::getline(stream, strX);
        std::getline(stream, strY);
        std::getline(stream, strZ);
        opData->SetEnd(Vector3d{ ToDouble(strX), ToDouble(strY), ToDouble(strZ) });
    }

    OwnerPtr<WallObject> opDbObject = NEW_AS_OWNER_PTR(WallObject);
    opDbObject->SetName(StringUtil::ToWString(name));
    opDbObject->SetData(TransferOwnership(opData));

    opIDbObject = TransferOwnershipCast<IDbObject>(opDbObject);
    return true;
}
